#ifndef SCOPE_H
#define SCOPE_H

// Some notes on scopes: read this or I will gut you like a fish.
// The ONLY scope to be defined with the constructor is called global, and is the global scope (no shit).
   // While using graft_sub on global or graft_super on the new scope might work, that leaves another thing that points to the subscope and is less friendly all around.
// The global scope having no superscopes is the terminating condition for lookup functions; do NOT use graft_super from global.
// Scopes contain scope pointers, not other scopes. Make this mistake and I will gut you WITH a fish.
   // Also, use message passing rather than the dot operator when referencing subscopes.
// I AM AN AWESOME SEXY BEAST
// The code is a template that takes a typename T and uses it as the type for the data; this way, we can fix untyped data seperately from scoping.

#include <vector>
#include <map>

template <class keytype, class T>
class scope
{
   public:
      scope()  // make a new scope; should only be needed for global. also sets the global value for its scope to this scope, which is useful for pseudodynamic operations
      {
         superscope = NULL;
         global = this;
         name.push_back('g');
         name.push_back('l');
         name.push_back('o');
         name.push_back('b');
         name.push_back('a');
         name.push_back('l');
      };
      
      std::map<keytype, T> variables;
      std::vector< scope<keytype, T> *> subscopes;
      scope<keytype, T> * superscope;
      scope<keytype, T> * global;     // stores the global scope for the structure, used for detach() and detach_sub()
      keytype name;
      
      scope<keytype, T> * get_path(std::vector<keytype>);
      
      void add_var(keytype, T);
      void add_path_var(std::vector<keytype>, keytype, T);
      scope<keytype, T> * add_scope(keytype); // adds a new subscope with a given name; this, NOT scope(); is how most scopes are made.
      scope<keytype, T> * add_path_scope(std::vector<keytype>, keytype);
      
      T get_var(keytype);
      T get_path_var(std::vector<keytype>, keytype);
      scope<keytype, T> * get_scope(keytype);
      scope<keytype, T> * get_path_scope(std::vector<keytype>, keytype);
      bool is_superscope(scope<keytype, T> *);
      bool is_subscope(scope<keytype, T> *);
      
      void detach();
      void detach_sub(keytype);
      
      scope<keytype, T> * attach(scope<keytype, T> *);
      scope<keytype, T> * attach_sub(scope<keytype, T> *);
      
      void send_to_sub(scope<keytype, T>, keytype);
      void copy_to_sub(scope<keytype, T>, keytype);
      scope<keytype, T> * make_sub_send(keytype);
      scope<keytype, T> * make_sub_copy(keytype);
};

#endif
